package cn.edu.hnu.gpg.service;

import cn.edu.hnu.gpg.api.error.InvalidArgumentException;
import cn.edu.hnu.gpg.dao.AdministratorMapper;
import cn.edu.hnu.gpg.dao.StudentMapper;
import cn.edu.hnu.gpg.dao.TeacherMapper;
import cn.edu.hnu.gpg.dao.UserMapper;
import cn.edu.hnu.gpg.dto.Account;
import cn.edu.hnu.gpg.entity.*;
import cn.edu.hnu.gpg.entity.enums.UserType;
import cn.edu.hnu.gpg.util.PasswordUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.NonNull;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.SessionAttribute;

import java.util.Base64;
import java.util.List;
import java.util.Random;

@Service
public class AdminServiceImpl implements AdminService{

    private AdministratorMapper administratorMapper;
    private UserService userService;
    private StudentService studentService;
    private TeacherService teacherService;

    @Autowired
    public AdminServiceImpl(AdministratorMapper administratorMapper, UserService userService, StudentService studentService, TeacherService teacherService){
        this.administratorMapper = administratorMapper;
        this.userService = userService;
        this.studentService = studentService;
        this.teacherService = teacherService;
    }

    @Override
    public Administrator findAdminByUser(int user_id) {
        if(user_id <= 0)
            return null;
        AdministratorExample administratorExample = new AdministratorExample();
        administratorExample.or().andUserIdEqualTo(user_id);
        List<Administrator> administrators = administratorMapper.selectByExample(administratorExample);
        return  administrators.size() > 0 ? administrators.get(0) : null;
    }

    @Override
    public boolean updateName(int user_id,String newName) {
        if(user_id <= 0 || newName == null)
            return false;

        Administrator administrator = findAdminByUser(user_id);
        administrator.setName(newName);
        return administratorMapper.updateByPrimaryKey(administrator)>=1;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean createAccounts(List<Account> accounts) {

        if (accounts == null || accounts.size() < 1) {
            throw new IllegalArgumentException("Accounts is null or empty.");
        }

        for (Account account : accounts) {
            switch (account.getUserType()) {
                case S:
                    Student student = account.getStudent();
                    if (student == null)
                        throw new IllegalArgumentException("Missing property 'Account.student'.\nAccount index: " + accounts.indexOf(account));
                    int studentId = studentService.createStudentAccount(student);
                    if (studentId <= 0)
                        throw new IllegalArgumentException("Creating student account failed.\nAccount index: " + accounts.indexOf(account));
                    break;
                case T:
                    Teacher teacher = account.getTeacher();
                    if (teacher == null)
                        throw new IllegalArgumentException("Missing property 'Account.student'.\nAccount index: " + accounts.indexOf(account));
                    int teacherId = teacherService.createTeacherAccount(teacher);
                    if (teacherId <= 0)
                        throw new RuntimeException("Creating teacher account failed.\nAccount index: " + accounts.indexOf(account));
                    break;

                    default:
                        throw new RuntimeException("Invalid use type: " + account.getUserType() + "\nAccount index: " + accounts.indexOf(account));
            }
        }

        return true;
    }
}
